package csharp.cauth.listeners;

import java.util.HashMap;
import java.util.logging.Level;

import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerChatEvent;
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
import org.bukkit.event.player.PlayerDropItemEvent;
import org.bukkit.event.player.PlayerInteractEntityEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerInventoryEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerKickEvent;
import org.bukkit.event.player.PlayerListener;
import org.bukkit.event.player.PlayerLoginEvent;
import org.bukkit.event.player.PlayerLoginEvent.Result;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.event.player.PlayerPickupItemEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.inventory.PlayerInventory;

import csharp.cauth.CAuth;
import csharp.cauth.Language;
import csharp.cauth.PlayersSL;
import csharp.cauth.PluginConfig;
import csharp.cauth.properties.InventoryProp;
import csharp.cauth.properties.PlayerProp;
import csharp.cauth.utils.Log;

/**
 * @author Ярослав (CSharp) Player listener for authorization.
 */
public class CAPlayerListener extends PlayerListener
{
	private final CAuth plugin;
	public HashMap<Player, Integer> tasks = new HashMap<Player, Integer>();

	public CAPlayerListener(CAuth instance)
	{
		plugin = instance;
	}

	@Override
	public void onPlayerJoin(PlayerJoinEvent event)
	{
		final Player player = event.getPlayer();

		player.sendMessage(ChatColor.RED + "[CAuth] CAuth plugin written by "
				+ ChatColor.GREEN + "CSharp" + ChatColor.RED + ".");

		if (!CAuth.authorized.contains(player))
		{
			player.sendMessage(ChatColor.RED + "[CAuth] "
					+ Language.AUTHORIZE_OR_REGISTER_TO_PLAY);
			player.teleport(player.getWorld().getSpawnLocation());

			PlayerInventory inventory = player.getInventory();

			CAuth.unauthorized.put(player, new InventoryProp(inventory));

			Integer taskId = plugin.getServer().getScheduler()
					.scheduleAsyncDelayedTask(plugin, new Runnable()
					{
						@Override
						public void run()
						{
							tasks.remove(player);

							if (!CAuth.authorized.contains(player))
							{
								player.kickPlayer("[CAuth] "
										+ Language.YOU_NEED_AUTHORIZE_TO_PLAY);
							}
						}
					}, PluginConfig.kickPlayerAfter * 10);

			tasks.put(player, taskId);

			inventory.clear();
			inventory.setBoots(null);
			inventory.setChestplate(null);
			inventory.setHelmet(null);
			inventory.setLeggings(null);
		}
	}

	@Override
	public void onPlayerKick(PlayerKickEvent event)
	{
		if (PluginConfig.kickSameNicks)
		{
			if (event.getReason() == "Logged in from another location.")
			{
				event.setCancelled(true);
			}
		}
	}

	@Override
	public void onPlayerLogin(PlayerLoginEvent event)
	{
		if (PluginConfig.kickSameNicks)
		{
			for (Player player : plugin.getServer().getOnlinePlayers())
			{
				if (player != event.getPlayer()
						&& player.getName().equalsIgnoreCase(
								event.getPlayer().getName()))
				{
					event.setResult(Result.KICK_OTHER);
					event.setKickMessage("[CAuth] "
							+ Language.THIS_NICKNAME_ALREADY_IN_USE);

					break;
				}
			}
		}
	}

	@Override
	public void onPlayerQuit(PlayerQuitEvent event)
	{
		Player player = event.getPlayer();

		if (CAuth.authorized.contains(player))
		{
			if (PluginConfig.rememberOperators && player.isOp())
			{
				if (PluginConfig.rememberUsePermissions)
				{
					if (CAuth.permissionHandler == null)
					{
						Log.log(Level.INFO,
								"No permissions plugin installed, remembering by OP.");

						PluginConfig.rememberUsePermissions = false;

						return;
					}

					String[] groups = CAuth.permissionHandler.getGroups(player
							.getWorld().getName(), player.getName());

					if (groups != null && PluginConfig.rememberGroups != null)
					{
						for (String group : groups)
						{
							if (PluginConfig.rememberGroups.contains(group))
							{
								return;
							}
						}
					}
				}
				else
					return;
			}

			CAuth.authorized.remove(player);

			PlayerProp temp = null;

			for (PlayerProp playerProp : CAuth.players)
			{
				if (playerProp.getLogin().equalsIgnoreCase(player.getName()))
				{
					temp = playerProp;

					break;
				}
			}

			if (temp != null)
			{
				CAuth.players.remove(temp);

				temp.setLastLoc(player.getLocation());

				CAuth.players.add(temp);

				if (PluginConfig.useMySQL)
					PlayersSL.updateLocation(temp.getId(), temp.getLastLoc());
				else
					PlayersSL.savePlayers();
			}
		}
		else
		{
			if (CAuth.unauthorized.containsKey(player))
			{
				PlayerInventory inventory = player.getInventory();
				InventoryProp inventoryProp = CAuth.unauthorized.get(player);

				inventory.setContents(inventoryProp.getItems());

				inventory.setBoots(CAuth.unauthorized.get(player).getBoots());
				inventory.setChestplate(CAuth.unauthorized.get(player)
						.getChest());
				inventory.setLeggings(CAuth.unauthorized.get(player)
						.getLeggings());
				inventory.setHelmet(CAuth.unauthorized.get(player).getHelmet());

				if (tasks.containsKey(player))
				{
					plugin.getServer().getScheduler()
							.cancelTask(tasks.get(player));

					tasks.remove(player);
				}
			}
		}
	}

	@Override
	public void onPlayerMove(PlayerMoveEvent event)
	{
		Player player = event.getPlayer();

		if (!CAuth.authorized.contains(player))
		{
			player.teleport(player.getWorld().getSpawnLocation());
		}
	}

	@Override
	public void onPlayerCommandPreprocess(PlayerCommandPreprocessEvent event)
	{
		String[] split = event.getMessage().substring(1).split(" ");

		if (split[0].equalsIgnoreCase("register")
				|| split[0].equalsIgnoreCase("login"))
		{
			return;
		}

		Player player = event.getPlayer();

		if (!CAuth.authorized.contains(player))
		{
			player.sendMessage("[CAuth] " + Language.YOU_CANT_USE_THIS_COMMAND);

			event.setCancelled(true);
		}

	}

	@Override
	public void onPlayerChat(PlayerChatEvent event)
	{
		Player player = event.getPlayer();

		if (!CAuth.authorized.contains(player))
		{
			event.setCancelled(true);
		}
	}

	@Override
	public void onInventoryOpen(PlayerInventoryEvent event)
	{
		Player player = event.getPlayer();

		if (!CAuth.authorized.contains(player))
		{
			player.kickPlayer("[CAuth] " + Language.CANT_OPEN_INVENTORY);
		}
	}

	@Override
	public void onPlayerDropItem(PlayerDropItemEvent event)
	{
		Player player = event.getPlayer();

		if (!CAuth.authorized.contains(player))
		{
			// Items destroyed when dropped, depend on inventory protection.
			event.setCancelled(true);
		}
	}

	@Override
	public void onPlayerPickupItem(PlayerPickupItemEvent event)
	{
		Player player = event.getPlayer();

		if (!CAuth.authorized.contains(player))
		{
			// Cloning items. Don't need.
			/*
			 * player.getWorld().dropItemNaturally(player.getLocation(),
			 * event.getItem().getItemStack());
			 */

			event.setCancelled(true);
		}
	}

	@Override
	public void onPlayerInteract(PlayerInteractEvent event)
	{
		Player player = event.getPlayer();

		if (!CAuth.authorized.contains(player))
		{
			event.setCancelled(true);
		}
	}

	@Override
	public void onPlayerInteractEntity(PlayerInteractEntityEvent event)
	{
		Player player = event.getPlayer();

		if (!CAuth.authorized.contains(player))
		{
			event.setCancelled(true);
		}
	}
}
